﻿// 功能：不支持滚动的列表框（对应UiList_2）
// 描述：
// 作者：温伟鹏
// 日期：2010/6/1 14:02:35

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Drawing;
using MeizuSDK.Drawing;
using System.Diagnostics;

namespace MeizuSDK.Presentation
{
    /// <summary>
    /// 不支持滚动的列表框（对应UiList_2，需要与ScrollableControl配合使用）
    /// </summary>
    public class UnscrollableListBox : ListControlBase
    {
        #region DllImport
        [DllImport("MZFCWrapper.dll")]
        private static extern IntPtr UiList_2WrapperCtor(DrawItemDelegate onDrawItem, MouseEventFunc onLButtonDown,
            MouseEventFunc onLButtonUp, MouseEventFunc onMouseMove);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperDrawDefaultItem(IntPtr pObj, IntPtr hdcDst, int nIndex, ref RECT prcItem, ref RECT prcWin, ref RECT prcUpdate);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiList_2WrapperGetSelectedIndex(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperSetSelectedIndex(IntPtr pObj, int index);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperSetItemHeight(IntPtr pObj, int nHeight);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiList_2WrapperCalcItemHeight(IntPtr pObj, int index);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperAddItem(IntPtr pObj, [MarshalAsAttribute(UnmanagedType.LPWStr)] string strText);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperRemoveItem(IntPtr pObj, int index);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperRemoveAll(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiList_2WrapperCalcIndexOfPos(IntPtr pObj, uint x, uint y);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool UiList_2WrapperCalcItemRect(IntPtr pObj, int index, ref RECT prcWin, ref RECT pRect);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperScrollTo(IntPtr pObj, int nScrollToType, int nDstTopPos, bool bAnimate);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperScrollStart(IntPtr pObj, double fScrollSpeed);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperScrollStop(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperEnableGridlines(IntPtr pObj, bool bEnable);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool UiList_2WrapperIsGridlinesEnabled(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperEnableUltraGridlines(IntPtr pObj, bool bEnable);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool UiList_2WrapperIsUltraGridlinesEnabled(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiList_2WrapperInvalidateItem(IntPtr pObj, int index);
        #endregion

        #region 私有变量
        /// <summary>
        /// 默认列表项高度
        /// </summary>
        private int defaultItemHeight;
        /// <summary>
        /// 列表项绘制函数委托
        /// </summary>
        private DrawItemDelegate drawItemDelegate;
        #endregion

        #region 公共属性
        /// <summary>
        /// 获取或设置列表当前选中的项索引
        /// </summary>
        public override int SelectedIndex
        {
            get
            {
                return UiList_2WrapperGetSelectedIndex(Handle);
            }
            set
            {
                if (value > 0 || value < Items.Count)
                {
                    Items.SetItemSelected(value, true);
                    UiList_2WrapperSetSelectedIndex(Handle, value);
                    InternalItemSelect(value);
                    InvalidateItem(value);
                    Update();
                }
            }
        }
        /// <summary>
        /// 获取或设置列表项默认高度
        /// </summary>
        public override int DefaultItemHeight
        {
            get
            {
                return defaultItemHeight;
            }
            set
            {
                if (value != this.defaultItemHeight)
                {
                    this.defaultItemHeight = value;
                    UiList_2WrapperSetItemHeight(Handle, value);
                }
            }
        }
        /// <summary>
        /// 获取或设置一个标志，指示列表是否绘制列表线
        /// </summary>
        public override bool GridLines
        {
            get
            {
                return UiList_2WrapperIsGridlinesEnabled(Handle);
            }
            set
            {
                UiList_2WrapperEnableGridlines(Handle, value);
            }
        }
        /// <summary>
        /// 获取或设置一个标志，指示列表是否绘制额外列表线
        /// </summary>
        public override bool UltraGridLines
        {
            get
            {
                return UiList_2WrapperIsUltraGridlinesEnabled(Handle);
            }
            set
            {
                UiList_2WrapperEnableUltraGridlines(Handle, value);
            }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 构造不支持滚动的列表框
        /// </summary>
        public UnscrollableListBox()
        {
            drawItemDelegate = new DrawItemDelegate(InternalDrawItem);

            Handle = UiList_2WrapperCtor(drawItemDelegate, LButtonDownDelegate, LButtonUpDelegate, MouseMoveDelegate);
            SetID();
            DefaultItemHeight = 70;
            NotifyMessage = true;// 启用鼠标消息
        }
        #endregion

        #region 函数

        #region 内部函数
        /// <summary>
        /// 添加列表项
        /// </summary>
        /// <param name="text">列表项文本</param>
        internal override void AddItem(string text)
        {
            UiList_2WrapperAddItem(Handle, text);
        }
        /// <summary>
        /// 移除指定索引的列表项
        /// </summary>
        /// <param name="index"></param>
        internal override void RemoveItem(int index)
        {
            UiList_2WrapperRemoveItem(Handle, index);
        }
        /// <summary>
        /// 移除所有的列表项
        /// </summary>
        internal override void RemoveAllItems()
        {
            UiList_2WrapperRemoveAll(Handle);
        }
        #endregion

        /// <summary>
        /// 绘制默认列表项
        /// </summary>
        /// <param name="hdcDst">设备上下文句柄</param>
        /// <param name="prcItem">列表项所在矩形</param>
        /// <param name="prcWin">列表控件所在矩形</param>
        /// <param name="prcUpdate">待更新的矩形区域</param>
        protected override void DrawDefaultItem(IntPtr hdcDst, int nIndex, ref RECT prcItem, ref RECT prcWin, ref RECT prcUpdate)
        {
            UiList_2WrapperDrawDefaultItem(Handle, hdcDst, nIndex, ref prcItem, ref prcWin, ref prcUpdate);
        }
        /// <summary>
        /// 获取指定索引处的列表项高度
        /// </summary>
        /// <param name="index">列表项索引</param>
        /// <returns>返回此列表项高度</returns>
        public override int GetItemHeight(int index)
        {
            return UiList_2WrapperCalcItemHeight(Handle, index);
        }
        /// <summary>
        /// 开始滚动
        /// </summary>
        /// <param name="scrollSpeed">滚动速度</param>
        public override void ScrollStart(double scrollSpeed)
        {
            UiList_2WrapperScrollStart(Handle, scrollSpeed);
        }
        /// <summary>
        /// 停止滚动
        /// </summary>
        public override void ScrollStop()
        {
            UiList_2WrapperScrollStop(Handle);
        }
        /// <summary>
        /// 滚动列表内容到指定位置
        /// </summary>
        /// <param name="scrollType">滚动类型</param>
        /// <param name="dstTopPos">目的为止。当ScrollType=ScrollToPos时才有效</param>
        /// <param name="animate">是否显示滚动过程</param>
        public override void ScrollTo(ScrollType scrollType, int dstTopPos, bool animate)
        {
            UiList_2WrapperScrollTo(Handle, (int)scrollType, dstTopPos, animate);
        }
        /// <summary>
        /// 计算某一坐标出的列表项的索引
        /// </summary>
        /// <param name="xPos">X坐标</param>
        /// <param name="yPos">Y坐标</param>
        /// <returns>列表项索引</returns>
        public override int CalcItemIndexOfPos(int xPos, int yPos)
        {
            return UiList_2WrapperCalcIndexOfPos(Handle, (uint)xPos, (uint)yPos);
        }
        /// <summary>
        /// 计算指定索引的列表项所在矩形区域
        /// </summary>
        /// <param name="index">列表项索引</param>
        /// <returns></returns>
        public override Rectangle CalcItemRectangle(int index)
        {
            RECT prcWin = RECT.FromXYWH(X, Y, Width, Height);
            RECT itemRect = new RECT();

            UiList_2WrapperCalcItemRect(Handle, index, ref prcWin, ref itemRect);

            return itemRect.ToRectangle();
        }
        /// <summary>
        /// 将指定索引的列表项设置为无效，在下次刷新时会重绘
        /// </summary>
        /// <param name="index">列表项索引</param>
        public override void InvalidateItem(int index)
        {
            if (index < 0 || index >= Items.Count)
                return;
            UiList_2WrapperInvalidateItem(Handle, index);
        }
        /// <summary>
        /// 鼠标左键按下消息
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLButtonDown(MouseEventArgs e)
        {
            LastX = e.X;
            LastY = e.Y;

            int index = CalcItemIndexOfPos(e.X, e.Y);

            if (ContainsItem(index))
            {
                MouseDown = true;
                LastClickedIndex = index;
                InvalidateItem(LastClickedIndex);
            }
            else
            {
                MouseDown = false;
                LastClickedIndex = -1;
                Invalidate();
            }

            Update();

            base.OnLButtonDown(e);
        }
        /// <summary>
        /// 鼠标左键抬起消息
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLButtonUp(MouseEventArgs e)
        {
            if (e.X != LastX || e.Y != LastY)
            {
                if (MouseDown)
                {
                    MouseDown = false;
                    LastClickedIndex = -1;
                    Invalidate();
                    Update();
                }
                return;
            }

            MouseDown = false;

            int index = CalcItemIndexOfPos(e.X, e.Y);

            if (ContainsItem(index))
            {
                SelectedIndex = -1;
                LastClickedIndex = index;
                base.OnLButtonUp(e);
                OnClick(new ListBoxClickEventArgs(index));
                return;
            }
            else
            {
                LastClickedIndex = -1;
                Invalidate();
                Update();
                base.OnLButtonUp(e);
            }
        }
        #endregion
    }
}
